package com.siwei.mes.common.aspect;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenmaolin
 * @version 1.0
 * @date 2023/4/1
 * @Description 入参输出切面
 */
@Slf4j
@Aspect
@Component
public class WebLogAspect {
    /**
     * 用来记录请求进入的时间，防止多线程时出错，这里用了ThreadLocal
     */
    ThreadLocal<Long> startTime = new ThreadLocal<>();

    List<String> ignoreUrl = new ArrayList<>();

    {
        ignoreUrl.add("/mes-platform/rwdextraPrintRecord/create");
    }

    /**
     * 定义切入点
     */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) || @annotation(org.springframework" +
            ".web.bind.annotation.PostMapping)  || @annotation(org.springframework.web.bind.annotation.GetMapping) ")
    public void requestLog() {
    }

    /**
     * 方法之前执行，日志打印请求信息
     *
     * @param joinPoint joinPoint
     */
    @Before("requestLog()")
    public void doBefore(JoinPoint joinPoint) {
        startTime.set(System.currentTimeMillis());
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();

        String method = request.getMethod();

        String requestURI = request.getRequestURI();

        if (ignoreUrl.contains(requestURI)) {
            if (StpUtil.isLogin()) {
                log.info("【用户】：{}，【请求接口】:{}，【请求方式】：{}", StpUtil.getLoginIdAsLong(), request.getRequestURI(), request.getMethod());
            } else {
                log.info("【请求接口】:{}，【请求方式】：{}", request.getRequestURI(), request.getMethod());
            }
            return;
        }

        try {
            if ("GET".equalsIgnoreCase(method)) {
                if (StpUtil.isLogin()) {
                    log.info("【用户】：{}，【请求接口】:{}，【请求方式】：{}，【请求参数】：{}", StpUtil.getLoginIdAsLong(), request.getRequestURI(), request.getMethod(), request.getQueryString());
                    // log.info("【用户】：{}，【请求接口】:{}，【请求方式】：{}", StpUtil.getLoginIdAsLong(), request.getRequestURI(), request.getMethod());
                } else {
                    log.info("【请求接口】:{}，【请求方式】：{}，【请求参数】：{}", request.getRequestURI(), request.getMethod(), request.getQueryString());
                    // log.info("【请求接口】:{}，【请求方式】：{}", request.getRequestURI(), request.getMethod());
                }
            } else {
                Object[] args = joinPoint.getArgs();
                Object[] params = new Object[args.length];
                for (int i = 0; i < args.length; i++) {
                    if (!(args[i] instanceof HttpServletRequest) && !(args[i] instanceof HttpServletResponse) && !(args[i] instanceof MultipartFile)) {
                        params[i] = args[i];
                    }
                }
                /**打印当前的请求路径,请求参数，如果需要打印其他的信息可以到request中去拿*/
                if (StpUtil.isLogin()) {
                    log.info("【用户】：{}，【请求接口】:{}，【请求方式】：{}，【请求参数】：{}", StpUtil.getLoginIdAsLong(), request.getRequestURI(), request.getMethod(), JSON.toJSON(params));
                    // log.info("【用户】：{}，【请求接口】:{}，【请求方式】：{}", StpUtil.getLoginIdAsLong(), request.getRequestURI(), request.getMethod());
                } else {
                    log.info("【请求接口】:{}，【请求方式】：{}，【请求参数】：{}", request.getRequestURI(), request.getMethod(), JSON.toJSON(params));
                    // log.info("【请求接口】:{}，【请求方式】：{}", request.getRequestURI(), request.getMethod());
                }
            }
        } catch (Exception e) {
            log.info("解析失败！【请求接口】:{}，【请求方式】：{}，【错误信息】：{}", request.getRequestURI(), request.getMethod(), e);
        }
    }


    /**
     * 方法返回之前执行，打印才返回值以及方法消耗时间
     *
     * @param response 返回值
     */
    @AfterReturning(returning = "response", pointcut = "requestLog()")
    public void doAfterRunning(Object response) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
//        /**打印返回值信息*/
//        log.info("【响应返回】:{}   ", JSON.toJSON(response));
//        /**打印请求耗时*/
        long time = System.currentTimeMillis() - startTime.get();
        try {
            log.info("【请求接口】:{}，【本次请求响应时间】: [{}ms]", request.getRequestURI(), time);
        } catch (Exception e) {
            log.info("【本次请求响应时间】: [{}ms]", time);
        }
    }
}

